Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

40장. WAF — 엣지에서 걸러내는 보안

이 장에서 말하고자 하는 것

CloudFront까지 깔면 사용자가 들어오는 길은 정리된다.

그런데 그 길에는 다음이 섞여 들어온다.

  • SQL 인젝션 시도
  • XSS 시도
  • 크롤러
  • 무차별 로그인 시도

이걸 애플리케이션 직전에서 미리 걸러내는 도구가

AWS WAF (Web Application Firewall)

다.

CloudFront · ALB · API Gateway 같은 엣지/입구 단계에
WAF를 끼워 둔다.


1. WAF가 막는 것

WAF는 HTTP 요청을 검사해 다음을 막는다.

  • OWASP Top 10에 가까운 공격 (SQLi, XSS, 경로 탐색 등)
  • 알려진 악성 IP/봇
  • 비정상적으로 잦은 요청 (Brute force)
  • 지정한 국가/IP 차단
  • 사용자 정의 패턴

2. WAF가 못 막는 것

WAF가 만능은 아니다.

  • 비즈니스 로직 취약점 (권한 우회, 잘못된 상태 전이)
  • 정상으로 보이는 정교한 봇
  • 인증 후 발생하는 내부 권한 문제

WAF는 첫 번째 그물이지 마지막 방어선이 아니다
애플리케이션 단계의 검증을 대체하지 않는다


3. WAF의 구성 요소

Web ACL

WAF의 최상위 단위.
하나의 보호 묶음이다.

Web ACL
 ├─ Rule 1
 ├─ Rule 2
 └─ Default action (allow / block)

Rule

요청이 어떤 패턴이면 어떻게 할지의 정의.

  • 매칭 조건: 헤더 / 쿼리 / 바디 / IP 등
  • 동작: ALLOW / BLOCK / COUNT / CAPTCHA

Rule Group

여러 룰을 묶은 단위.
직접 만들 수도 있고 AWS가 만들어 제공하는 것도 있다.


4. AWS Managed Rules — 가장 먼저 켜야 할 것

AWS가 제공하는 룰 묶음이다.

룰 그룹내용
Core rule setOWASP 기반 일반 보호
Known bad inputs알려진 악성 입력
SQL databaseSQL 인젝션
Linux / Unix명령 주입
Bot Control봇 탐지
Anonymous IP listVPN / Tor / 호스팅 IP

WAF를 처음 켤 때는 우선 Core + Known bad inputs + SQL 부터


5. Rate-based Rule — 폭증 차단

같은 IP에서 짧은 시간에 너무 많이 들어오는 요청을 막는다.

5분 동안 같은 IP가 2,000회 초과 → BLOCK

로그인 페이지, 비밀번호 재설정, 인증 코드 검증처럼
악용되기 쉬운 엔드포인트에 따로 더 엄격한 임계를 건다.


6. Count 모드 — 일단 보기만 하기

새 룰을 켤 때 곧장 BLOCK 으로 두면
정상 트래픽까지 막아 사고가 난다.

WAF는 룰을 COUNT 모드로 둘 수 있다.

COUNT → 매칭은 잡지만 차단은 안 함

로그를 며칠 보고 오탐이 없는 걸 확인한 뒤
BLOCK으로 전환하는 게 운영의 표준 흐름이다.


7. WAF는 어디에 다는가

WAF는 다음 리소스에 붙는다.

  • CloudFront
  • ALB
  • API Gateway
  • Cognito User Pool
  • AppSync
사용자 → [WAF + CloudFront] → ALB → ECS

CloudFront에 다는 게 가장 흔하다.
공격 트래픽이 origin까지 도달하기 전에 막는다.

가장 바깥에 한 번, 필요하면 ALB에도 추가로


8. 우리 서비스에서

척추 그림에서 WAF 위치다.

[사용자]
   ↓
[WAF + CloudFront]   ← 여기, 첫 그물
   ├─ /api/* → ALB
   │           ↓
   │       [(선택) WAF + ALB]   ← 두 번째 그물
   │           ↓
   │       [ECS]
   └─ /static/* → S3
  • 모든 트래픽은 CloudFront WAF 통과
  • /api/* 만 별도 ALB WAF로 한 번 더 (필요 시)
  • CloudFront WAF는 us-east-1 글로벌 범위

9. 직접 확인해보기 — CLI

Web ACL 만들기

aws wafv2 create-web-acl \
  --name my-acl \
  --scope CLOUDFRONT \
  --default-action Allow={} \
  --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=my-acl \
  --region us-east-1

--scope 가 중요하다.

CLOUDFRONT → CloudFront에 붙일 WAF (반드시 us-east-1)
REGIONAL   → ALB · APIGW 등에 붙일 WAF (해당 리전)

Web ACL을 리소스에 붙이기

aws wafv2 associate-web-acl \
  --web-acl-arn <acl-arn> \
  --resource-arn <alb-arn>

차단된 요청 로그

WAF 로그를 CloudWatch Logs · S3 · Firehose 로 보낼 수 있다.

aws wafv2 put-logging-configuration ...

운영에서는 로그 없이 WAF를 켜지 않는다.
오탐이 났을 때 추적이 안 된다.


10. 코드로는 이렇게 생겼다 — Terraform

CloudFront에 붙일 WAF 한 벌의 모양이다.

resource "aws_wafv2_web_acl" "main" {
  provider = aws.us_east_1   # CloudFront WAF는 us-east-1

  name  = "main-acl"
  scope = "CLOUDFRONT"

  default_action {
    allow {}
  }

  rule {
    name     = "AWSManagedRulesCommonRuleSet"
    priority = 1

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        vendor_name = "AWS"
        name        = "AWSManagedRulesCommonRuleSet"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "common"
      sampled_requests_enabled   = true
    }
  }

  rule {
    name     = "RateLimit"
    priority = 10

    action {
      block {}
    }

    statement {
      rate_based_statement {
        limit              = 2000
        aggregate_key_type = "IP"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "rate-limit"
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "main-acl"
    sampled_requests_enabled   = true
  }
}

이 정도가 처음 켤 때의 적정 출발선이다.


11. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. 룰을 추가하자마자 BLOCK 으로 둔다

정상 트래픽이 같이 잡혀 장애가 난다.

새 룰은 COUNT 로 며칠 → 로그 확인 → BLOCK 전환

안티패턴 2. WAF 로그를 안 켠다

차단됐는데 왜 차단됐는지 추적이 안 된다.

WAF는 로그 없이 운영하지 않는다

안티패턴 3. WAF에만 의존하고 애플리케이션 검증을 안 한다

WAF는 그물이지 잠금장치가 아니다.

입력 검증 · 인증 · 권한 검사 모두 애플리케이션에 있어야 한다

안티패턴 4. CloudFront WAF를 서울 리전에서 만들려고 한다

scope = CLOUDFRONT 인데 region = ap-northeast-2 → 실패

CloudFront WAF는 반드시 us-east-1


12. 한 줄로 정리

WAF는 엣지에서 악성 트래픽을 거르는 첫 번째 그물이며,
애플리케이션 검증을 대체하지 않는 추가 계층이다


13. 이 장의 핵심 정리

  1. WAF는 HTTP 레벨 공격을 엣지에서 거르는 보안 계층이다.
  2. Web ACL · Rule · Rule Group의 3단 구조다.
  3. AWS Managed Rules로 시작해 환경에 맞게 보강한다.
  4. Rate-based Rule로 폭증 트래픽과 무차별 시도를 막는다.
  5. 새 룰은 COUNT 모드로 검증 후 BLOCK으로 옮긴다.
  6. WAF는 첫 그물이지 마지막 방어선이 아니다.
  7. CloudFront WAF는 us-east-1, ALB / APIGW WAF는 해당 리전.